/*
 * @Author: dgflash
 * @Date: 2022-09-01 18:00:28
 * @LastEditors: dgflash
 * @LastEditTime: 2022-09-05 14:21:54
 */
import { ecs } from "./ECS";
import { ECSEntity } from "./ECSEntity";

/**
 * ECS 实体组（优化版）
 * 
 * 负责缓存符合特定 Matcher 规则的实体集合
 * 
 * 优化要点：
 * 1. 使用数组代替 Array.from 转换，减少对象创建
 * 2. 优化 count 更新逻辑，减少重复判断
 * 3. 缓存 entity getter，避免每次访问数组
 * 4. 优化 clear 方法，批量清理
 * 5. 添加快速路径优化（has 检查前置）
 */
export class ECSGroup<E extends ECSEntity = ECSEntity> {
    /** 实体筛选规则 */
    private readonly matcher: ecs.IMatcher;

    /** 实体 Map（快速查找） */
    private _matchEntities: Map<number, E> = new Map();

    /** 实体数组缓存（快速遍历） */
    private _entitiesCache: E[] | null = null;

    /**
     * 符合规则的实体数组
     * 
     * 优化：复用数组，避免重复创建
     */
    get matchEntities(): E[] {
        if (this._entitiesCache === null) {
            // 优化：直接从 Map.values() 转数组，比 Array.from 快
            this._entitiesCache = [];
            this._entitiesCache.length = this._matchEntities.size;
            let i = 0;
            for (const entity of this._matchEntities.values()) {
                this._entitiesCache[i++] = entity;
            }
        }
        return this._entitiesCache;
    }

    /**
     * 当前 Group 中实体的数量
     * 
     * 优化：直接使用 Map.size，避免手动维护
     */
    get count(): number {
        return this._matchEntities.size;
    }

    /**
     * 获取第一个实体（快速访问）
     * 
     * 优化：使用迭代器直接获取，避免构建完整数组
     */
    get entity(): E | undefined {
        // 优化：直接获取第一个值，不需要构建完整数组
        return this._matchEntities.values().next().value;
    }

    /** 新进入 Group 的实体 */
    private _enteredEntities: Map<number, E> | null = null;
    
    /** 从 Group 移除的实体 */
    private _removedEntities: Map<number, E> | null = null;

    constructor(matcher: ecs.IMatcher) {
        this.matcher = matcher;
    }

    /**
     * 组件添加或移除时的回调
     * 
     * 优化要点：
     * 1. 前置 has 检查，减少不必要的匹配判断
     * 2. 分离添加和移除逻辑，减少嵌套
     * 3. 只在必要时使缓存失效
     */
    onComponentAddOrRemove(entity: E): void {
        const eid = entity.eid;
        const hadEntity = this._matchEntities.has(eid);
        const matchesNow = this.matcher.isMatch(entity);

        // 优化：提前判断状态，避免重复操作
        if (matchesNow === hadEntity) {
            return; // 状态未改变，无需处理
        }

        if (matchesNow) {
            // 实体现在匹配规则，添加到 Group
            this._matchEntities.set(eid, entity);
            this._entitiesCache = null; // 缓存失效

            // 处理进入/移除跟踪
            if (this._enteredEntities) {
                this._enteredEntities.set(eid, entity);
                this._removedEntities!.delete(eid);
            }
        } else {
            // 实体不再匹配规则，从 Group 移除
            this._matchEntities.delete(eid);
            this._entitiesCache = null; // 缓存失效

            // 处理进入/移除跟踪
            if (this._enteredEntities) {
                this._enteredEntities.delete(eid);
                this._removedEntities!.set(eid, entity);
            }
        }
    }

    /**
     * 监听实体进入和移除事件
     * 
     * @param enteredEntities 新进入的实体集合
     * @param removedEntities 移除的实体集合
     */
    watchEntityEnterAndRemove(enteredEntities: Map<number, E>, removedEntities: Map<number, E>): void {
        this._enteredEntities = enteredEntities;
        this._removedEntities = removedEntities;
    }

    /**
     * 清空 Group
     * 
     * 优化：批量清理，减少操作次数
     */
    clear(): void {
        // 优化：只清理非空集合
        if (this._matchEntities.size > 0) {
            this._matchEntities.clear();
            this._entitiesCache = null;
        }

        if (this._enteredEntities && this._enteredEntities.size > 0) {
            this._enteredEntities.clear();
        }

        if (this._removedEntities && this._removedEntities.size > 0) {
            this._removedEntities.clear();
        }
    }

    /**
     * 检查实体是否在 Group 中
     * 
     * 优化：直接查询 Map，O(1) 复杂度
     */
    has(entity: E): boolean {
        return this._matchEntities.has(entity.eid);
    }

    /**
     * 检查实体 ID 是否在 Group 中
     * 
     * 优化：直接使用 eid 查询，避免实体对象传递
     */
    hasById(eid: number): boolean {
        return this._matchEntities.has(eid);
    }

    /**
     * 获取指定实体
     * 
     * @param eid 实体 ID
     * @returns 实体对象，不存在则返回 undefined
     */
    get(eid: number): E | undefined {
        return this._matchEntities.get(eid);
    }

    /**
     * 遍历所有实体（高性能版本）
     * 
     * 优化：直接遍历 Map.values()，避免构建临时数组
     * 
     * @param callback 回调函数
     */
    forEach(callback: (entity: E, index: number) => void): void {
        let index = 0;
        for (const entity of this._matchEntities.values()) {
            callback(entity, index++);
        }
    }

    /**
     * 判断 Group 是否为空
     * 
     * 优化：直接判断 size，比检查数组长度快
     */
    get isEmpty(): boolean {
        return this._matchEntities.size === 0;
    }
}